
#ifndef _MapObstacle_H_
#define _MapObstacle_H_

#include "Utils/Vector2D.h"

#include <vector>

class MapObstacle {
  public:
    MapObstacle(Vector2D world_min_coord, Vector2D world_max_coord, 
                float obstacle_expand_size_tight, float obstacle_expand_size_loose);
    ~MapObstacle();

    bool load(const std::vector<int> &obstacle_map, int width, int height, int label);
    void render(void);

    
    bool pointInside(Vector2D point, bool use_collision_space, bool tight_collision_space);

    // See Map.h for explanation of "use_collision_space" argument
    bool collideRaySegment(Vector2D start, Vector2D end, Vector2D &inormal, 
                           Vector2D &ipoint, bool use_collision_space, bool tight_collision_space);

    bool collideSphere(Vector2D centre, float radius, Vector2D &normal, Vector2D &collision_point,
                       Vector2D &constraint_free_point);

  private:

    Vector2D world_min_coord, world_max_coord;
    Vector2D obstacle_min_coord, obstacle_max_coord;
    float half_grid_length;
    float obstacle_expand_size_tight, obstacle_expand_size_loose;

    std::vector<Vector2D> corners;

    // Collision space corners define the obstacle in collision space, that is, if a ships
    // position is inside the collision space obstacle, then it has collided with the obstacle.
    // as long as the position is outside the collision space obstacle, its not collided with 
    // the real obstacle.
    std::vector<Vector2D> collision_space_corners_tight;
    std::vector<Vector2D> collision_space_corners_loose;

    std::vector<Vector2D> normals;
    std::vector<Vector2D> inside_points; // TODO i dont really need to keep this around after the display list is built.
    unsigned int dl_id;

    
    void generateDisplayList(void);
    void generateNormals(void);
    void generateCollisionObstacle(float size_of_object, std::vector<Vector2D> &result_buffer); 
    void simplifyPolygon(void); // cull out unnecessary vertices.

    bool findNeighbouringEdgePixel(const std::vector<int> &obstacle_map, int width, int height, int label, 
                                   int cx, int cy, int notx, int noty, int &x, int &y);
    bool findEdgePixel(const std::vector<int> &obstacle_map, int width, int height, int label, int &x, int &y);
    bool isEdgePixel(const std::vector<int> &obstacle_map, int width, int height, int label, int x, int y);
    bool isEmptyPixel(const std::vector<int> &obstacle_map, int width, int height, int x, int y);

    bool haveCommonEmptyNeighbours(const std::vector<int> &obstacle_map, int width, int height,
                                   int x1, int y1, int x2, int y2);
    bool isNeighbourOf(int x, int y, int tx, int ty);

    Vector2D pixelToPosition(int pixel_x, int pixel_y, int width, int height);
};

#endif

